package musicalgo.data;

import ai.neuralnet.NNBuilder;
import ai.neuralnet.NeuralNetwork;
import data.SequentialData;

import java.util.ArrayList;
import java.util.List;

public class DataIO
{
    public static ArrayList<SequentialData> loadSongs(String path)
    {
        ArrayList<SequentialData> dataList = new ArrayList<SequentialData>();
        List<String> lines = FileIO.readLines(path);
        for (String s : lines)
        {
            dataList.add(parseData(s));
        }

        return dataList;
    }

    public static void writePredictions(String path, int[] predictions)
    {
        List<String> lines = new ArrayList<String>(predictions.length);
        for (int i = 0; i < predictions.length; i++)
        {
            lines.add(Integer.toString(predictions[i]));
        }

        FileIO.writeLines(lines, path);
    }

    public static ArrayList<double[]> loadDesiredOutputs(String path, int categoryCount)
    {
        List<String> lines = FileIO.readLines(path);
        ArrayList<double[]> values = new ArrayList<double[]>(lines.size());
        for (String l : lines)
        {
            int category = Integer.parseInt(l);
            double[] array = new double[categoryCount];
            array[category] = 1;
            values.add(array);
        }

        return values;
    }

    private static SequentialData parseData(String s)
    {
        double[] values = parseDoubles(FileIO.spaceSplit(s));
        int dimensions = 25;
        SequentialData sequentialData = new SequentialData();
        double[] dataPoint = new double[dimensions];
        for (int i = 0; i < values.length; i++)
        {
            if (i % dimensions == 0)
            {
                dataPoint = new double[dimensions];
            }

            dataPoint[i % dimensions] = values[i];

            if (i % dimensions == dimensions - 1)
            {
                sequentialData.addDataPoint(dataPoint);
            }
        }

        return sequentialData;

    }

    private static double[] parseDoubles(String[] values)
    {
        double[] result = new double[values.length];
        for (int i = 0; i < values.length; i++)
        {
            result[i] = Double.parseDouble(values[i]);
        }
        return result;
    }

    private static List<Double> parseDoublesList(List<String> values)
    {
        List<Double> result = new ArrayList<Double>(values.size());
        for (String str : values)
        {
            result.add(Double.parseDouble(str));
        }
        return result;
    }

    public static NeuralNetwork loadNetwork(NNBuilder builder, String weightsFile)
    {
        NeuralNetwork net = builder.build();

        List<String> strings = FileIO.readLines(weightsFile);

        net.setWeights(parseDoublesList(strings));

        return net;
    }


    /**
     * writes the weights to a file
     */
    public static void writeWeights(String name, NeuralNetwork<?> n)
    {
        ArrayList<String> weights = new ArrayList<String>();
        for (Double d : n.getWeights())
        {
            weights.add(d.toString());
        }

        FileIO.writeLines(weights, name + ".nw");
    }
}
